<!doctype html>



  


<html class="theme-next mist use-motion" lang="zh-Hans">
<head>
  <meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>



<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />















  
  
  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />




  
  
  
  

  
    
    
  

  

  

  

  

  
    
    
    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
  






<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />

<link href="/css/main.css?v=5.1.0" rel="stylesheet" type="text/css" />


  <meta name="keywords" content="mysql,InnoDB,半同步复制" />








  <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico?v=5.1.0" />






<meta name="description" content="Mysql复制架构的演变 在2000年，MySQL 3.23.15版本引入了Replication。Replication作为一种准实时同步方式，得到广泛应用。这个时候的Replicaton的实现涉及到两个线程，一个在Master，一个在Slave。Slave的I/O和SQL功能是作为一个线程，从Master获取到event后直接apply，没有relay log。这种方式使得读取event的速度">
<meta name="keywords" content="mysql,InnoDB,半同步复制">
<meta property="og:type" content="article">
<meta property="og:title" content="Mysql的半同步复制（转）">
<meta property="og:url" content="http://www.zhizus.com/2018-08-1-Mysql的复制-半同步复制.html">
<meta property="og:site_name" content="郑大侠的博客">
<meta property="og:description" content="Mysql复制架构的演变 在2000年，MySQL 3.23.15版本引入了Replication。Replication作为一种准实时同步方式，得到广泛应用。这个时候的Replicaton的实现涉及到两个线程，一个在Master，一个在Slave。Slave的I/O和SQL功能是作为一个线程，从Master获取到event后直接apply，没有relay log。这种方式使得读取event的速度">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="http://www.zhizus.com/images/1533113503024.png">
<meta property="og:image" content="http://www.zhizus.com/images/1533114981912.png">
<meta property="og:image" content="http://www.zhizus.com/images/1533115526404.png">
<meta property="og:image" content="http://www.zhizus.com/images/1533115537629.png">
<meta property="og:image" content="http://www.zhizus.com/images/1533115565194.png">
<meta property="og:image" content="http://www.zhizus.com/images/1533115575514.png">
<meta property="og:image" content="http://www.zhizus.com/images/1533115605738.png">
<meta property="og:image" content="http://www.zhizus.com/images/1533115625469.png">
<meta property="og:image" content="http://www.zhizus.com/images/1533115636525.png">
<meta property="og:updated_time" content="2018-08-01T10:23:41.353Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Mysql的半同步复制（转）">
<meta name="twitter:description" content="Mysql复制架构的演变 在2000年，MySQL 3.23.15版本引入了Replication。Replication作为一种准实时同步方式，得到广泛应用。这个时候的Replicaton的实现涉及到两个线程，一个在Master，一个在Slave。Slave的I/O和SQL功能是作为一个线程，从Master获取到event后直接apply，没有relay log。这种方式使得读取event的速度">
<meta name="twitter:image" content="http://www.zhizus.com/images/1533113503024.png">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Mist',
    sidebar: {"position":"left","display":"post"},
    fancybox: true,
    motion: true,
    duoshuo: {
      userId: '0',
      author: '博主'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: "",
      labels: ""
    }
  };
</script>



  <link rel="canonical" href="http://www.zhizus.com/2018-08-1-Mysql的复制-半同步复制.html"/>





  <title> Mysql的半同步复制（转） | 郑大侠的博客 </title>
</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?f75c9cec9ecead0dfce9a108b9688072";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>










  
  
    
  

  <div class="container sidebar-position-left page-post-detail ">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/"  class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">郑大侠的博客</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
            
            首页
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/archives" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
            
            归档
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/categories" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br />
            
            分类
          </a>
        </li>
      
        
        <li class="menu-item menu-item-crossed">
          <a href="http://zhizus.com" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-camera-retro"></i> <br />
            
            穿越
          </a>
        </li>
      
        
        <li class="menu-item menu-item-about">
          <a href="/about" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-user"></i> <br />
            
            关于
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-mysql " itemscope itemtype="http://schema.org/Article">
    <link itemprop="mainEntityOfPage" href="http://www.zhizus.com/2018-08-1-Mysql的复制-半同步复制.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="DempeZheng">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="https://avatars3.githubusercontent.com/u/6263631?v=3&s=466">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="郑大侠的博客">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">
            
            
              
                Mysql的半同步复制（转）
              
            
          </h1>
        

        <div class="post-meta">
          <span class="post-time">
            

            

            
          </span>

          

          
            
          

          
          
             <span id="/2018-08-1-Mysql的复制-半同步复制.html" class="leancloud_visitors" data-flag-title="Mysql的半同步复制（转）">
               <span class="post-meta-divider">|</span>
               <span class="post-meta-item-icon">
                 <i class="fa fa-eye"></i>
               </span>
               
                 <span class="leancloud-visitors-count"></span>
             </span>
          

          

          

          

        </div>
      </header>
    


    <div class="post-body" itemprop="articleBody">

      
      

      
        <h2 id="Mysql复制架构的演变"><a href="#Mysql复制架构的演变" class="headerlink" title="Mysql复制架构的演变"></a>Mysql复制架构的演变</h2><blockquote>
<p>在2000年，MySQL 3.23.15版本引入了Replication。Replication作为一种准实时同步方式，得到广泛应用。这个时候的Replicaton的实现涉及到两个线程，一个在Master，一个在Slave。Slave的I/O和SQL功能是作为一个线程，从Master获取到event后直接apply，没有relay log。这种方式使得读取event的速度会被Slave replay速度拖慢，当主备存在较大延迟时候，会导致大量binary log没有备份到Slave端。</p>
</blockquote>
<hr>
<blockquote>
<p>在2002年，MySQL 4.0.2版本将Slave端event读取和执行独立成两个线程（IO线程和SQL线程），同时引入了relay log。IO线程读取event后写入relay log，SQL线程从relay log中读取event然后执行。这样即使SQL线程执行慢，Master的binary log也会尽可能的同步到Slave。当Master宕机，切换到Slave，不会出现大量数据丢失。</p>
</blockquote>
<hr>
<blockquote>
<p>在2010年MySQL 5.5版本之前，一直采用的是这种异步复制的方式。主库的事务执行不会管备库的同步进度，如果备库落后，主库不幸crash，那么就会导致数据丢失。于是在MySQL在5.5中就顺其自然地引入了半同步复制，主库在应答客户端提交的事务前需要保证至少一个从库接收并写到relay log中。那么半同步复制是否可以做到不丢失数据呢？下面分析。</p>
</blockquote>
<hr>
<blockquote>
<p>在2016年，MySQL在5.7.17中引入了一个全新的技术，称之为InnoDB Group Replication。目前官方MySQL 5.7.17基于Group replication的全同步技术已经问世，全同步技术带来了更多的数据一致性保障。相信是未来同步技术一个重要方向，值得期待。MySQL 5.7 Group Replication</p>
</blockquote>
<p>根据上面提到的这几种复制协议，分别对应MySQL几种复制类型，分别是异步、半同步、全同步。
<img src="./images/1533113503024.png" alt="Alt text"></p>
<h2 id="Mysql的复制"><a href="#Mysql的复制" class="headerlink" title="Mysql的复制"></a>Mysql的复制</h2><ul>
<li>异步复制（<code>Asynchronous replication</code>）</li>
<li>全同步复制（<code>Fully synchronous replication</code>）</li>
<li>半同步复制（<code>Semisynchronous replication</code>）</li>
</ul>
<h3 id="异步复制"><a href="#异步复制" class="headerlink" title="异步复制"></a>异步复制</h3><p>MySQL默认的复制即是异步的，主库在执行完客户端提交的事务后会立即将结果返给给客户端，并不关心从库是否已经接收并处理，这样就会有一个问题，主如果crash掉了，此时主上已经提交的事务可能并没有传到从上，如果此时，强行将从提升为主，可能导致新主库的数据不完整。</p>
<h4 id="存在的问题"><a href="#存在的问题" class="headerlink" title="存在的问题"></a>存在的问题</h4><p>异步复制binlog到从库，从库IO线程接收到后写中继日志（relay log），如果由于网络原因导致relay log延时太多。这时候主库宕机，提升从库为主库，新的主库就会丢失数据。</p>
<h3 id="全同步复制"><a href="#全同步复制" class="headerlink" title="全同步复制"></a>全同步复制</h3><p>指当主库执行完一个事务，所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回，所以全同步复制的性能必然会收到严重的影响。</p>
<blockquote>
<p>目前官方MySQL 5.7.17基于Group replication的全同步技术已经问世，全同步技术带来了更多的数据一致性保障。相信是未来同步技术一个重要方向，值得期待。MySQL 5.7 Group Replication</p>
</blockquote>
<h3 id="半同步复制"><a href="#半同步复制" class="headerlink" title="半同步复制"></a>半同步复制</h3><p>鉴于异步复制比较容易造成数据丢失，Mysql在5.6的版本的时候支持半同步复制<br>半同步复制介于异步复制和全同步复制之间，主库在执行完客户端提交的事务后不是立刻返回给客户端，而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制，半同步复制提高了数据的安全性，同时它也造成了一定程度的延迟，这个延迟最少是一个TCP/IP往返的时间。所以，半同步复制最好在低延时的网络中使用。</p>
<h4 id="半同步复制的特性"><a href="#半同步复制的特性" class="headerlink" title="半同步复制的特性"></a>半同步复制的特性</h4><ul>
<li><p>半同步在网络超时的场景下会退化为异步复制</p>
<blockquote>
<p>如果在等待过程中，等待时间已经超过了配置的超时时间，没有任何一个从节点通知当前事务，那么此时主库会自动转换为异步复制，当至少一个半同步从节点赶上来时，主库便会自动转换为半同步方式的复制。</p>
</blockquote>
</li>
<li><p>半同步复制必须是在主库和从库两端都开启</p>
<blockquote>
<p>如果从库开了半同步复制，但是主库没有开启半同步复制，则会默认为异步复制</p>
</blockquote>
</li>
</ul>
<h4 id="半同步复制的原理"><a href="#半同步复制的原理" class="headerlink" title="半同步复制的原理"></a>半同步复制的原理</h4><p><img src="./images/1533114981912.png" alt="Alt text"></p>
<h4 id="半同步复制存在的问题"><a href="#半同步复制存在的问题" class="headerlink" title="半同步复制存在的问题"></a>半同步复制存在的问题</h4><p>半同步复制可能会出现幻读或者数据丢失的情况。
在MySQL 5.5~5.6使用after_commit的模式下，客户端事务在存储引擎层提交后，在得到从库确认的过程中，主库宕机了。此时，即主库在等待Slave ACK的时候，虽然没有返回当前客户端，但事务已经提交，其他客户端会读取到已提交事务。如果Slave端还没有读到该事务的events，同时主库发生了crash，然后切换到备库。那么之前读到的事务就不见了，出现了<code>幻读</code></p>
<h4 id="MySQL-5-7半同步复制的改进"><a href="#MySQL-5-7半同步复制的改进" class="headerlink" title="MySQL 5.7半同步复制的改进"></a>MySQL 5.7半同步复制的改进</h4><p>现在我们已经知道，在半同步环境下，主库是在事务提交之后等待Slave ACK，所以才会有数据不一致问题。所以这个Slave ACK在什么时间去等待，也是一个很关键的问题了。因此MySQL针对半同步复制的问题，在5.7.2引入了Loss-less Semi-Synchronous，在调用binlog sync之后，engine层commit之前等待Slave ACK。这样只有在确认Slave收到事务events后，事务才会提交。在commit之前等待Slave ACK，同时可以堆积事务，利于group commit，有利于提升性能。</p>
<ul>
<li>支持无损复制（Loss-less Semi-Synchronous）</li>
<li>性能提升，支持发送binlog和接受ack的异步化</li>
<li>性能提升，控制主库接收slave写事务成功反馈数量</li>
<li>性能提升, Binlog互斥锁改进</li>
</ul>
<h5 id="支持无损复制（Loss-less-Semi-Synchronous）"><a href="#支持无损复制（Loss-less-Semi-Synchronous）" class="headerlink" title="支持无损复制（Loss-less Semi-Synchronous）"></a>支持无损复制（Loss-less Semi-Synchronous）</h5><p>在Loss-less Semi-Synchronous模式下，master在调用binlog sync之后，engine层commit之前等待Slave ACK（需要收到至少一个Slave节点回复的ACK后）。这样只有在确认Slave收到事务events后，master事务才会提交，然后把结果返回给客户端。此时此事务才对其他事务可见。在这种模式下解决了after_commit模式带来的幻读和数据丢失问题，因为主库没有提交事务。但也会有个问题，假设主库在存储引擎提交之前挂了，那么很明显这个事务是不成功的，但由于对应的Binlog已经做了Sync操作，从库已经收到了这些Binlog，并且执行成功，相当于在从库上多了数据，也算是有问题的，但多了数据，问题一般不算严重。这个问题可以这样理解，作为MySQL，在没办法解决分布式数据一致性问题的情况下，它能保证的是不丢数据，多了数据总比丢数据要好。</p>
<p>无损复制其实就是对semi sync增加了rpl_semi_sync_master_wait_point参数，来控制半同步模式下主库在返回给会话事务成功之前提交事务的方式。rpl_semi_sync_master_wait_point该参数有两个值：AFTER_COMMIT和AFTER_SYNC</p>
<p>第一个值：AFTER_COMMIT（5.6默认值）</p>
<p>master将每个事务写入binlog（sync_binlog=1），传递到slave刷新到磁盘(sync_relay=1)，同时主库提交事务。master等待slave反馈收到relay log，只有收到ACK后master才将commit OK结果反馈给客户端。</p>
<p><img src="./images/1533115526404.png" alt="Alt text"></p>
<p>第二个值：AFTER_SYNC（5.7默认值，但5.6中无此模式）</p>
<p>master将每个事务写入binlog , 传递到slave刷新到磁盘(relay log)。master等待slave反馈接收到relay log的ack之后，再提交事务并且返回commit OK结果给客户端。 即使主库crash，所有在主库上已经提交的事务都能保证已经同步到slave的relay log中。</p>
<p><img src="./images/1533115537629.png" alt="Alt text"></p>
<p>半同步复制与无损复制的对比</p>
<p>1.1 ACK的时间点不同</p>
<p>半同步复制在InnoDB层的Commit Log后等待ACK，主从切换会有数据丢失风险。
无损复制在MySQL Server层的Write binlog后等待ACK，主从切换会有数据变多风险。
1.2 主从数据一致性</p>
<p>半同步复制意味着在Master节点上，这个刚刚提交的事物对数据库的修改，对其他事物是可见的。因此，如果在等待Slave ACK的时候crash了，那么会对其他事务出现幻读，数据丢失。
无损复制在write binlog完成后，就传输binlog，但还没有去写commit log，意味着当前这个事物对数据库的修改，其他事物也是不可见的。因此，不会出现幻读，数据丢失风险。
因此5.7引入了无损复制（after_sync）模式，带来的主要收益是解决after_commit导致的master crash后数据丢失问题，因此在引入after_sync模式后，所有提交的数据已经都被复制，故障切换时数据一致性将得到提升。</p>
<h5 id="性能提升，支持发送binlog和接受ack的异步化"><a href="#性能提升，支持发送binlog和接受ack的异步化" class="headerlink" title="性能提升，支持发送binlog和接受ack的异步化"></a>性能提升，支持发送binlog和接受ack的异步化</h5><p>旧版本的semi sync受限于dump thread ，原因是dump thread承担了两份不同且又十分频繁的任务：传送binlog给slave ，还需要等待slave反馈信息，而且这两个任务是串行的，dump thread必须等待slave返回之后才会传送下一个events事务。dump thread已然成为整个半同步提高性能的瓶颈。在高并发业务场景下，这样的机制会影响数据库整体的TPS 。</p>
<p><img src="./images/1533115565194.png" alt="Alt text"></p>
<p>为了解决上述问题，在5.7版本的semi sync框架中，独立出一个Ack Receiver线程 ，专门用于接收slave返回的ack请求，这将之前dump线程的发送和接受工作分为了两个线程来处理。这样master上有两个线程独立工作，可以同时发送binlog到slave，和接收slave的ack信息。因此半同步复制得到了极大的性能提升。这也是MySQL 5.7发布时号称的Faster semi-sync replication。</p>
<p><img src="./images/1533115575514.png" alt="Alt text"></p>
<p>但是在MySQL 5.7.17之前，这个Ack Receiver线程采用了select机制来监听slave返回的结果，然而select机制监控的文件句柄只能是0-1024，当超过1024时，用户在MySQL的错误日志中或许会收到类似如下的报错，更有甚者会导致MySQL发生宕机。</p>
<p>semi-sync master failed on net_flush() before waiting for slave reply.</p>
<p>MySQL 5.7.17版本开始，官方修复了这个bug，开始使用poll机制来替换原来的select机制，从而可以避免上面的问题。其实poll调用本质上和select没有区别，只是在I/O句柄数理论上没有上限了，原因是它是基于链表来存储的。但是同样有缺点：比如大量的fd的数组被整体复制于用户态和内核地址空间之间，而不管这样的复制是不是有意义。poll还有一个特点是“水平触发”，如果报告了fd后，没有被处理，那么下次poll时会再次报告该fd。</p>
<p>其实在高性能软件中都是用另外一种调用机制，名为epoll，高性能的代表，比如Nginx，haproxy等都是使用epoll。可能poll的复杂性比epoll低，另外对于ack receiver线程来说可能poll足矣。</p>
<h5 id="性能提升，控制主库接收slave写事务成功反馈数量"><a href="#性能提升，控制主库接收slave写事务成功反馈数量" class="headerlink" title="性能提升，控制主库接收slave写事务成功反馈数量"></a>性能提升，控制主库接收slave写事务成功反馈数量</h5><p>MySQL 5.7新增了rpl_semi_sync_master_wait_slave_count参数，可以用来控制主库接受多少个slave写事务成功反馈，给高可用架构切换提供了灵活性。如图所示，当count值为2时，master需等待两个slave的ack。</p>
<p><img src="./images/1533115605738.png" alt="Alt text"></p>
<h5 id="性能提升-Binlog互斥锁改进"><a href="#性能提升-Binlog互斥锁改进" class="headerlink" title="性能提升, Binlog互斥锁改进"></a>性能提升, Binlog互斥锁改进</h5><p>旧版本半同步复制在主提交binlog的写会话和dump thread读binlog的操作都会对binlog添加互斥锁，导致binlog文件的读写是串行化的，存在并发度的问题。</p>
<p><img src="./images/1533115625469.png" alt="Alt text"></p>
<p>MySQL 5.7对binlog lock进行了以下两方面优化:</p>
<ol>
<li><p>移除了dump thread对binlog的互斥锁。</p>
</li>
<li><p>加入了安全边际保证binlog的读安全。</p>
</li>
</ol>
<p><img src="./images/1533115636525.png" alt="Alt text"></p>
<p>可以看到从replication功能引入后，官方MySQL一直在不停的完善，前进。同时我们可以发现当前原生的MySQL主备复制实现实际上很难在满足数据一致性的前提下做到高可用、高性能。</p>
<h2 id="补充"><a href="#补充" class="headerlink" title="补充"></a>补充</h2><p>1.Mysql 并行复制 
2.Mysql Slave延时的场景？</p>
<h2 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h2><p>这边文章写的思路很清晰完成，强烈案例，本文基本是复制过来的。
<a href="http://www.ywnds.com/?p=7023" target="_blank" rel="noopener">MySQL 5.7半同步复制技术</a></p>

      
    </div>

    <div>
      
        

      
    </div>

    <div>
      
        
  <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
    <div>大侠劫富济贫啦！</div>
    <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
      <span>赏</span>
    </button>
    <div id="QR" style="display: none;">
      
        <div id="wechat" style="display: inline-block">
          <img id="wechat_qr" src="/images/dempe/20180527112524.jpg" alt="DempeZheng WeChat Pay"/>
        </div>
      
      
    </div>
  </div>


      
    </div>

    <div>
      
        

      
    </div>

    <footer class="post-footer">
      

      
        
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/2018-07-31-Mysql文件-binlog日志.html" rel="next" title="MySql 文件-binlog">
                <i class="fa fa-chevron-left"></i> MySql 文件-binlog
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/2018-08-1-MVCC多版本并发读.html" rel="prev" title="MySql MVCC多版本并发读">
                MySql MVCC多版本并发读 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          
  <div class="comments" id="comments">
    
      <div id="SOHUCS"></div>
    
  </div>


        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview">
            站点概览
          </li>
        </ul>
      

      <section class="site-overview sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
          <img class="site-author-image" itemprop="image"
               src="https://avatars3.githubusercontent.com/u/6263631?v=3&s=466"
               alt="DempeZheng" />
          <p class="site-author-name" itemprop="name">DempeZheng</p>
           
              <p class="site-description motion-element" itemprop="description">請更固執，將自己謀生與擅長的事情做到最好</p>
          
        </div>
        <nav class="site-state motion-element">

          
            <div class="site-state-item site-state-posts">
              <a href="/archives">
                <span class="site-state-item-count">68</span>
                <span class="site-state-item-name">日志</span>
              </a>
            </div>
          

          
            
            
            <div class="site-state-item site-state-categories">
              <a href="/categories/index.html">
                <span class="site-state-item-count">23</span>
                <span class="site-state-item-name">分类</span>
              </a>
            </div>
          

          

        </nav>

        

        <div class="links-of-author motion-element">
          
            
              <span class="links-of-author-item">
                <a href="https://github.com/dempeZheng" target="_blank" title="GitHub">
                  
                    <i class="fa fa-fw fa-github"></i>
                  
                  GitHub
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="http://music.163.com/#/user/home?id=6758793" target="_blank" title="网易云音乐">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  网易云音乐
                </a>
              </span>
            
              <span class="links-of-author-item">
                <a href="https://www.zhihu.com/people/dempe" target="_blank" title="知乎">
                  
                    <i class="fa fa-fw fa-globe"></i>
                  
                  知乎
                </a>
              </span>
            
          
        </div>

        
        

        
        
          <div class="links-of-blogroll motion-element links-of-blogroll-inline">
            <div class="links-of-blogroll-title">
              <i class="fa  fa-fw fa-globe"></i>
              Links
            </div>
            <ul class="links-of-blogroll-list">
              
                <li class="links-of-blogroll-item">
                  <a href="http://www.wolfbe.com/" title="朗度云" target="_blank">朗度云</a>
                </li>
              
            </ul>
          </div>
        

        


      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#Mysql复制架构的演变"><span class="nav-number">1.</span> <span class="nav-text">Mysql复制架构的演变</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Mysql的复制"><span class="nav-number">2.</span> <span class="nav-text">Mysql的复制</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#异步复制"><span class="nav-number">2.1.</span> <span class="nav-text">异步复制</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#存在的问题"><span class="nav-number">2.1.1.</span> <span class="nav-text">存在的问题</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#全同步复制"><span class="nav-number">2.2.</span> <span class="nav-text">全同步复制</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#半同步复制"><span class="nav-number">2.3.</span> <span class="nav-text">半同步复制</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#半同步复制的特性"><span class="nav-number">2.3.1.</span> <span class="nav-text">半同步复制的特性</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#半同步复制的原理"><span class="nav-number">2.3.2.</span> <span class="nav-text">半同步复制的原理</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#半同步复制存在的问题"><span class="nav-number">2.3.3.</span> <span class="nav-text">半同步复制存在的问题</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#MySQL-5-7半同步复制的改进"><span class="nav-number">2.3.4.</span> <span class="nav-text">MySQL 5.7半同步复制的改进</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#支持无损复制（Loss-less-Semi-Synchronous）"><span class="nav-number">2.3.4.1.</span> <span class="nav-text">支持无损复制（Loss-less Semi-Synchronous）</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#性能提升，支持发送binlog和接受ack的异步化"><span class="nav-number">2.3.4.2.</span> <span class="nav-text">性能提升，支持发送binlog和接受ack的异步化</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#性能提升，控制主库接收slave写事务成功反馈数量"><span class="nav-number">2.3.4.3.</span> <span class="nav-text">性能提升，控制主库接收slave写事务成功反馈数量</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#性能提升-Binlog互斥锁改进"><span class="nav-number">2.3.4.4.</span> <span class="nav-text">性能提升, Binlog互斥锁改进</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#补充"><span class="nav-number">3.</span> <span class="nav-text">补充</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#参考文档"><span class="nav-number">4.</span> <span class="nav-text">参考文档</span></a></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright" >
  
  &copy; 
  <span itemprop="copyrightYear">2018</span>
  <span class="with-love">
    <i class="fa fa-"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">DempeZheng</span>
</div>



        

        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  






  
  <script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>

  
  <script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>

  
  <script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

  
  <script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>


  


  <script type="text/javascript" src="/js/src/utils.js?v=5.1.0"></script>

  <script type="text/javascript" src="/js/src/motion.js?v=5.1.0"></script>



  
  

  
  <script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.0"></script>
<script type="text/javascript" src="/js/src/post-details.js?v=5.1.0"></script>



  


  <script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.0"></script>



  


  




	





  





  





  






  





  

  
  <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.1.js"></script>
  <script>AV.initialize("dhzMp0HdJLWMCrt04bwybWzH-gzGzoHsz", "gH6FmxJiUaVLLRXQDWpkkIVv");</script>
  <script>
    function showTime(Counter) {
      var query = new AV.Query(Counter);
      var entries = [];
      var $visitors = $(".leancloud_visitors");

      $visitors.each(function () {
        entries.push( $(this).attr("id").trim() );
      });

      query.containedIn('url', entries);
      query.find()
        .done(function (results) {
          var COUNT_CONTAINER_REF = '.leancloud-visitors-count';

          if (results.length === 0) {
            $visitors.find(COUNT_CONTAINER_REF).text(0);
            return;
          }

          for (var i = 0; i < results.length; i++) {
            var item = results[i];
            var url = item.get('url');
            var time = item.get('time');
            var element = document.getElementById(url);

            $(element).find(COUNT_CONTAINER_REF).text(time);
          }
          for(var i = 0; i < entries.length; i++) {
            var url = entries[i];
            var element = document.getElementById(url);
            var countSpan = $(element).find(COUNT_CONTAINER_REF);
            if( countSpan.text() == '') {
              countSpan.text(0);
            }
          }
        })
        .fail(function (object, error) {
          console.log("Error: " + error.code + " " + error.message);
        });
    }

    function addCount(Counter) {
      var $visitors = $(".leancloud_visitors");
      var url = $visitors.attr('id').trim();
      var title = $visitors.attr('data-flag-title').trim();
      var query = new AV.Query(Counter);

      query.equalTo("url", url);
      query.find({
        success: function(results) {
          if (results.length > 0) {
            var counter = results[0];
            counter.fetchWhenSave(true);
            counter.increment("time");
            counter.save(null, {
              success: function(counter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(counter.get('time'));
              },
              error: function(counter, error) {
                console.log('Failed to save Visitor num, with error message: ' + error.message);
              }
            });
          } else {
            var newcounter = new Counter();
            /* Set ACL */
            var acl = new AV.ACL();
            acl.setPublicReadAccess(true);
            acl.setPublicWriteAccess(true);
            newcounter.setACL(acl);
            /* End Set ACL */
            newcounter.set("title", title);
            newcounter.set("url", url);
            newcounter.set("time", 1);
            newcounter.save(null, {
              success: function(newcounter) {
                var $element = $(document.getElementById(url));
                $element.find('.leancloud-visitors-count').text(newcounter.get('time'));
              },
              error: function(newcounter, error) {
                console.log('Failed to create');
              }
            });
          }
        },
        error: function(error) {
          console.log('Error:' + error.code + " " + error.message);
        }
      });
    }

    $(function() {
      var Counter = AV.Object.extend("Counter");
      if ($('.leancloud_visitors').length == 1) {
        addCount(Counter);
      } else if ($('.post-title-link').length > 1) {
        showTime(Counter);
      }
    });
  </script>



  

  

  

</body>
</html>
